package vv.lines.view.swing.utils;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
import static vv.lines.view.swing.utils.SwingLinesConstants.*;

/**
 * @author vpotapenko
 */
public class SwingResourceHolder {

    private static final Logger logger = Logger.getLogger(SwingResourceHolder.class.getName());

    private Map<Integer, Image> ballImages;
    private Map<Integer, Icon> previewBallIcons;
    private Map<Integer, Icon> championBallIcons;
    private Image gameImage;
    private Icon aboutIcon;
    private Icon exitIcon;
    private Icon newGameIcon;
    private Icon rulesIcon;
    private Icon gameIcon;

    public SwingResourceHolder(int maxValue) {
        initBallImages(maxValue);
        initPreviewBallIcons();
        initChampionBallImages();
        initSingleIcons();
    }

    public Image getBallImage(int color) {
        return ballImages.get(color);
    }

    public Icon getPreviewIcon(int color) {
        return previewBallIcons.get(color);
    }

    public Icon getChampionIcon(int color) {
        return championBallIcons.get(color);
    }

    public Image getGameImage() {
        return gameImage;
    }

    private void initChampionBallImages() {
        championBallIcons = new HashMap<Integer, Icon>();
        Set<Integer> keys = ballImages.keySet();
        for (Integer key : keys) {
            championBallIcons.put(key, createChampionBallImage(ballImages.get(key)));
        }
    }

    private Icon createChampionBallImage(Image ballImage) {
        BufferedImage image = new BufferedImage(16, 16, TYPE_INT_ARGB);
        Graphics g = image.createGraphics();
        g.drawImage(ballImage, 0, 0, image.getWidth(), image.getHeight(), null);

        return new ImageIcon(image);
    }

    private void initPreviewBallIcons() {
        previewBallIcons = new HashMap<Integer, Icon>();
        Set<Integer> keys = ballImages.keySet();
        for (Integer key : keys) {
            previewBallIcons.put(key, createPreviewBallIcon(ballImages.get(key)));
        }
    }

    private Icon createPreviewBallIcon(Image ballImage) {
        BufferedImage image = new BufferedImage(32, 32, TYPE_INT_ARGB);
        Graphics g = image.createGraphics();
        g.drawImage(ballImage, 0, 0, image.getWidth(), image.getHeight(), null);

        return new ImageIcon(image);
    }

    private void initBallImages(int maxValue) {
        ballImages = new HashMap<Integer, Image>();
        for (int i = 1; i < (maxValue + 1); i++) {
            ballImages.put(i, getImageByPath(String.format(BALL_TEMPLATE, PATH_TO_IMAGES, i)));
        }
    }

    private Image getImageByPath(String path) {
        InputStream is = getClass().getResourceAsStream(path);
        try {
            return is != null ? ImageIO.read(is) : null;
        } catch (IOException ex) {
            logger.log(Level.SEVERE, null, ex);
            return null;
        }
    }

    private void initSingleIcons() {
        gameImage = getImageByPath(PATH_TO_IMAGES + ICON_NAME);
        gameIcon = new ImageIcon(gameImage);
        aboutIcon = new ImageIcon(getImageByPath(PATH_TO_IMAGES + ABOUT_NAME));
        exitIcon = new ImageIcon(getImageByPath(PATH_TO_IMAGES + EXIT_NAME));
        newGameIcon = new ImageIcon(getImageByPath(PATH_TO_IMAGES + NEW_GAME_NAME));
        rulesIcon = new ImageIcon(getImageByPath(PATH_TO_IMAGES + RULES_NAME));
    }

    public Icon getAboutIcon() {
        return aboutIcon;
    }

    public Icon getExitIcon() {
        return exitIcon;
    }

    public Icon getNewGameIcon() {
        return newGameIcon;
    }

    public Icon getRulesIcon() {
        return rulesIcon;
    }

    public Icon getGameIcon() {
        return gameIcon;
    }
}
